package com.panda.common;

import com.google.common.io.Files;
import com.panda.command.Console;

import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/*
    文件处理器

    分析出所有的文件,并进行路径处理

 */
public class FileHandler extends ResourceHolder {


    //文件输入输出的两个根路径文件夹
    private File input, output;

    //charset为编码
    public FileHandler(File input, File output, Charset charset) {
        this.charset = charset;
        this.input = input;
        this.output = output;
    }


    //charset为编码
    public FileHandler(File input, Charset charset) {
        this.charset = charset;
        this.input = input;
    }

    private String clear(File file) {

        File[] files = file.listFiles();
        if (files != null) {
            for (File f : files) {

                if (f.isDirectory()) {
                    return clear(f);
                }

                if (!f.delete()) {
                    return f.getAbsolutePath();
                }

            }
        }

        return null;
    }


    //文件构建器
    private StringBuilder builder = new StringBuilder();

    //读入文件
    private String read(File f) throws IOException {
        BufferedReader reader = Files.newReader(f, charset);
        String line;
        while ((line = reader.readLine()) != null) {
            builder.append(line).append("\n");
        }
        //关流
        reader.close();
        String s = builder.toString();
        builder.delete(0, builder.length());
        return s;

    }

    //将js和jss放入对应的容器中
    private void jsAndCss(String fj, Map<String,String> container) throws FileNotFoundException {

        if (fj != null && !fj.equals("")) {
            String[] jf = fj.split(",");
            for (String j : jf) {
                if (!j.endsWith(".yml")) {
                    j = j + ".yml";
                }

                File file = files.get(j);

                //获取配置文件
                if (file != null) {
                    container.putAll(YamlLoader.load(file));
                }

            }
        }

    }


    //将路径下的文件层层展开
    private void fileMap(File file, String path) {
        File[] files = file.listFiles();

        if (files != null) {
            for (File f : files) {

                if (f.equals(output)) {
                    continue;
                }

                if (!f.isHidden()) {

                    if (f.isDirectory()) {

                        fileMap(f, path + f.getName() + "/");

                    } else
                        this.files.put(path + f.getName(), f);
                }
            }

        }
    }

    //这里并不会直接解析指令文件,而是在解析时再处理
    private void handleCommand() throws FileNotFoundException {

        String cd = (String) config.get("file.command");
        if (cd != null && !cd.equals("")) {
            String[] cs = cd.split(",");
            for (String c : cs) {
                if (!c.endsWith(".yml")) {
                    c += ".yml";
                }
                File file = files.get(c);
                if (file != null) {

                    //添加
                    this.commands.add(YamlLoader.load(file));

                }
            }
        }
    }

    private void handleDependency() throws Exception {

        String d = (String) config.get("file.dependency");

        if (d != null) {

            String[] cs = d.split(",");

            for (String c : cs) {

                if (!c.endsWith(".yml")) {
                    c += ".yml";
                }
                File file = files.get(c);
                if (file != null) {

                    this.dependencies.add(YamlLoader.load(file));

                }

            }

        }

    }


    //处理配置文件
    private void handleConfig() throws Exception {

        //处理command文件
        handleCommand();


        //处理js和css文件
        jsAndCss((String) config.get("file.js"), js);
        jsAndCss((String) config.get("file.css"), css);

        //找到.service文件
        for (String s : files.keySet()) {
            File file = files.get(s);
            if (file.getName().endsWith(".service")) {
                String st = read(file);
                if (!"".equals(st)) {
                    serviceTexts.add(st);
                }
            }
        }

        //.component文件
        for (String s : files.keySet()) {
            File file = files.get(s);
            if (file.getName().endsWith(".component")) {
                String st = read(file);
                if (!"".equals(st)) {
                    componentTexts.add(st);
                }
            }
        }

        //创建和panda文件目录相同的文件目录

        if (output != null)
            for (String s : files.keySet()) {
                File file = files.get(s);
                if (s.endsWith(".panda")) {
                    String st = read(file);
                    if (!"".equals(st)) {
                        String ofn = s.substring(0, s.lastIndexOf(".panda")) + ".html";
                        File of = new File(output, ofn);

                        //如果文件不存在
                        if (!of.exists()) {

                            File parent = new File(of.getParent());
                            if (!parent.exists()) {
                                parent.mkdirs();
                            }

                            //创建输出文件
                            if (!of.createNewFile()) {
                                throw new RuntimeException("创建文件失败:" + of.getAbsolutePath());
                            }
                        } else {
                            if (!of.isFile()) {
                                if (of.delete()) {
                                    if (!of.createNewFile()) {
                                        throw new RuntimeException("要求" + of.getAbsolutePath() + "必须是一个文件,但无法修正");
                                    }
                                } else {
                                    throw new RuntimeException("要求" + of.getAbsolutePath() + "必须是一个文件,但无法修正");
                                }

                            }

                        }

                        //创建了输出文件但是却失败了
                        PrintStream printStream = new PrintStream(of, charset.name());

                        //添加文件输出流
                        pandas.put(read(file), printStream);

                    }
                }
            }
    }

    private Map<String, File> files;


    @Override
    public void handle() throws Exception {

        //展开文件文件夹
        files = new HashMap<>();

        //可以不指定文件输出
        if (output != null) {

            if (output.exists()) {

                String clear = clear(output);

                if (clear != null) {
                    throw new IOException("输出路径必须是一个空白的文件夹,但该文件夹下存在无法被清空:" + clear + "无法被删除");
                }
            } else {
                if (!output.mkdirs()) {
                    throw new IOException("无法创建输出路径:" + output.getAbsolutePath());
                }
            }

        }

        fileMap(input, "");

        //配置文件
        File configFile = files.get("conf.properties");


        if (configFile == null) {
            throw new RuntimeException("conf.properties 是必须的文件");
        }

        Reader fileReader = new InputStreamReader(new FileInputStream(configFile), Console.charset);
        Properties properties = new Properties();
        properties.load(fileReader);
        fileReader.close();

        this.config = properties;

        //处理配置文件
        handleConfig();

        handleDependency();

    }


}
